/**
 * 图片优化工具
 * @description 提供WebP支持检测、响应式图片生成、懒加载、图片预加载等功能
 * @author 系统开发团队
 * @version 1.0.0
 */

// ==================== 接口定义 ====================

/**
 * 图片配置接口
 * @description 定义图片优化的各种配置选项
 */
interface ImageConfig {
  /** 原始图片路径 */
  src: string
  /** WebP格式图片路径，可选 */
  webpSrc?: string
  /** 图片alt属性 */
  alt: string
  /** 图片宽度（像素） */
  width?: number
  /** 图片高度（像素） */
  height?: number
  /** 是否启用懒加载，默认为true */
  lazy?: boolean
  /** 响应式图片sizes属性 */
  sizes?: string
  /** 响应式图片srcset属性 */
  srcset?: string
}

// ==================== 图片优化器类 ====================

/**
 * 图片优化器类
 * @description 提供图片格式检测、响应式图片生成、懒加载等功能
 */
class ImageOptimizer {
  /** WebP支持状态缓存，避免重复检测 */
  private webpSupported: boolean | null = null

  /**
   * 检测浏览器是否支持WebP格式
   * @description 通过加载WebP测试图片来检测浏览器支持情况
   * @returns {Promise<boolean>} 是否支持WebP格式
   * @example
   * const supportsWebP = await imageOptimizer.checkWebPSupport()
   * if (supportsWebP) {
   *   console.log('浏览器支持WebP格式')
   * }
   */
  async checkWebPSupport(): Promise<boolean> {
    // 如果已经检测过，直接返回缓存结果
    if (this.webpSupported !== null) {
      return this.webpSupported
    }

    return new Promise((resolve) => {
      const webP = new Image()
      webP.onload = webP.onerror = () => {
        // 如果图片高度为2，说明WebP格式被正确解析
        this.webpSupported = webP.height === 2
        resolve(this.webpSupported)
      }
      // 使用WebP测试图片进行检测
      webP.src = ''
    })
  }

  /**
   * 生成WebP图片URL
   * @description 根据原始图片路径生成对应的WebP格式图片路径
   * @param {string} originalSrc 原始图片路径
   * @returns {string} WebP图片路径
   * @example
   * const webpUrl = imageOptimizer.generateWebPUrl('/images/photo.jpg')
   * // 返回: '/images/photo.webp'
   */
  generateWebPUrl(originalSrc: string): string {
    // 在开发环境中，直接返回原始路径
    if (import.meta.env.DEV) {
      return originalSrc
    }

    // 在生产环境中，替换文件扩展名为.webp
    return originalSrc.replace(/\.(jpg|jpeg|png)$/i, '.webp')
  }

  /**
   * 生成响应式图片srcset
   * @description 为图片生成响应式srcset属性，支持不同屏幕尺寸
   * @param {string} src 原始图片路径
   * @param {number[]} sizes 图片尺寸数组，默认[320, 640, 960, 1280]
   * @returns {string} srcset字符串
   * @example
   * const srcset = imageOptimizer.generateSrcset('/images/photo.jpg', [320, 640, 960])
   * // 返回: '/images/photo.webp?w=320 320w, /images/photo.webp?w=640 640w, /images/photo.webp?w=960 960w'
   */
  generateSrcset(src: string, sizes: number[] = [320, 640, 960, 1280]): string {
    const webpSrc = this.generateWebPUrl(src)
    const srcset = sizes.map(size => `${webpSrc}?w=${size} ${size}w`).join(', ')
    return srcset
  }

  /**
   * 生成响应式图片sizes属性
   * @description 生成响应式图片的sizes属性，定义不同屏幕尺寸下的图片显示大小
   * @param {Record<string, string>} breakpoints 断点配置对象
   * @returns {string} sizes字符串
   * @example
   * const sizes = imageOptimizer.generateSizes({
   *   '320px': '100vw',
   *   '640px': '50vw'
   * })
   * // 返回: '(min-width: 320px) 100vw, (min-width: 640px) 50vw, 100vw'
   */
  generateSizes(breakpoints: Record<string, string> = {
    '320px': '100vw',
    '640px': '50vw',
    '960px': '33.33vw',
    '1280px': '25vw'
  }): string {
    return Object.entries(breakpoints)
      .map(([breakpoint, size]) => `(min-width: ${breakpoint}) ${size}`)
      .join(', ') + ', 100vw'
  }

  /**
   * 创建优化的图片元素
   * @description 根据配置创建优化的HTML图片元素，支持懒加载和响应式图片
   * @param {ImageConfig} config 图片配置对象
   * @returns {HTMLImageElement} 优化后的图片元素
   * @example
   * const img = imageOptimizer.createOptimizedImage({
   *   src: '/images/photo.jpg',
   *   webpSrc: '/images/photo.webp',
   *   alt: '风景照片',
   *   width: 800,
   *   height: 600,
   *   lazy: true
   * })
   */
  createOptimizedImage(config: ImageConfig): HTMLImageElement {
    const img = document.createElement('img')

    // 设置基本属性
    img.alt = config.alt
    if (config.width) img.width = config.width
    if (config.height) img.height = config.height

    // 设置懒加载（默认启用）
    if (config.lazy !== false) {
      img.loading = 'lazy'
    }

    // 设置响应式图片属性
    if (config.srcset) {
      img.srcset = config.srcset
    }

    if (config.sizes) {
      img.sizes = config.sizes
    }

    // 设置图片源（支持WebP回退）
    this.setImageSource(img, config)

    return img
  }

  /**
   * 设置图片源（支持WebP回退）
   * @description 根据浏览器支持情况设置最优的图片源
   * @param {HTMLImageElement} img 图片元素
   * @param {ImageConfig} config 图片配置
   * @private
   */
  private async setImageSource(img: HTMLImageElement, config: ImageConfig) {
    const supportsWebP = await this.checkWebPSupport()

    if (supportsWebP && config.webpSrc) {
      // 浏览器支持WebP且有WebP版本，使用WebP格式
      img.src = config.webpSrc
    } else {
      // 浏览器不支持WebP或没有WebP版本，使用原始格式
      img.src = config.src
    }
  }

  /**
   * 预加载单张图片
   * @description 预加载指定路径的图片，确保图片在需要时已经缓存
   * @param {string} src 图片路径
   * @returns {Promise<void>} 加载完成的Promise
   * @example
   * await imageOptimizer.preloadImage('/images/hero.jpg')
   * console.log('图片预加载完成')
   */
  preloadImage(src: string): Promise<void> {
    return new Promise((resolve, reject) => {
      const img = new Image()
      img.onload = () => resolve()
      img.onerror = () => reject(new Error(`Failed to load image: ${src}`))
      img.src = src
    })
  }

  /**
   * 批量预加载图片
   * @description 同时预加载多张图片
   * @param {string[]} srcs 图片路径数组
   * @returns {Promise<void>[]} Promise数组
   * @example
   * const promises = imageOptimizer.preloadImages([
   *   '/images/photo1.jpg',
   *   '/images/photo2.jpg',
   *   '/images/photo3.jpg'
   * ])
   * await Promise.all(promises)
   * console.log('所有图片预加载完成')
   */
  preloadImages(srcs: string[]): Promise<void>[] {
    return srcs.map(src => this.preloadImage(src))
  }

  /**
   * 获取图片尺寸
   * @description 获取指定图片的自然尺寸（宽度和高度）
   * @param {string} src 图片路径
   * @returns {Promise<{width: number, height: number}>} 图片尺寸对象
   * @example
   * const dimensions = await imageOptimizer.getImageDimensions('/images/photo.jpg')
   * console.log(`图片尺寸: ${dimensions.width}x${dimensions.height}`)
   */
  getImageDimensions(src: string): Promise<{ width: number, height: number }> {
    return new Promise((resolve, reject) => {
      const img = new Image()
      img.onload = () => {
        resolve({
          width: img.naturalWidth,
          height: img.naturalHeight
        })
      }
      img.onerror = () => reject(new Error(`Failed to get dimensions for: ${src}`))
      img.src = src
    })
  }
}

// ==================== 实例和导出 ====================

/** 全局图片优化器实例 */
export const imageOptimizer = new ImageOptimizer()

/**
 * 导出工具函数
 * @description 从imageOptimizer实例中导出所有公共方法，方便直接使用
 */
export const {
  checkWebPSupport,
  generateWebPUrl,
  generateSrcset,
  generateSizes,
  createOptimizedImage,
  preloadImage,
  preloadImages,
  getImageDimensions
} = imageOptimizer 